namespace NFreeMarker.Template
{
    /**
     * A base class for containers that wrap arbitrary Java objects into 
     * {@link TemplateModel} instances.
     *
     * @version $Id: WrappingTemplateModel.java,v 1.18.2.1 2005/12/07 00:41:23 revusky Exp $
     */

    public abstract class WrappingTemplateModel
    {
        private static IObjectWrapper _defaultObjectWrapper =
            DefaultObjectWrapper.Instance;

        private IObjectWrapper _objectWrapper;

        /**
         * Sets the default object wrapper that is used when a wrapping template
         * model is constructed without being passed an explicit object wrapper.
         * The default value is {@link ObjectWrapper#SIMPLE_WRAPPER}.
         * Note that {@link Configuration#setSharedVariable(string, object)} and
         * {@link Template#process(object, java.io.Writer)} don't use this setting,
         * they rather use whatever object wrapper their 
         * {@link Configuration#getObjectWrapper()} method returns.
         */

        public static void SetDefaultObjectWrapper(IObjectWrapper objectWrapper)
        {
            _defaultObjectWrapper = objectWrapper;
        }

        /**
         * Returns the default object wrapper that is used when a wrapping template
         * model is constructed without being passed an explicit object wrapper.
         * Note that {@link Configuration#setSharedVariable(string, object)} and
         * {@link Template#process(object, java.io.Writer)} don't use this setting,
         * they rather use whatever object wrapper their 
         * {@link Configuration#getObjectWrapper()} method returns.
         */

        public static IObjectWrapper GetDefaultObjectWrapper()
        {
            return _defaultObjectWrapper;
        }

        /**
         * Protected constructor that creates a new wrapping template model using
         * the default object wrapper.
         */

        protected WrappingTemplateModel()
            : this(_defaultObjectWrapper)
        {
        }

        /**
         * Protected constructor that creates a new wrapping template model using
         * the specified object wrapper.
         * @param objectWrapper the wrapper to use. If null is passed, the default
         * object wrapper is used.
         */

        protected WrappingTemplateModel(IObjectWrapper objectWrapper)
        {
            _objectWrapper = objectWrapper ?? _defaultObjectWrapper;
            if (_objectWrapper == null)
            {
                _objectWrapper = _defaultObjectWrapper = new DefaultObjectWrapper();
            }
        }

        /**
         * Returns the object wrapper instance used by this wrapping template model.
         */

        public IObjectWrapper GetObjectWrapper()
        {
            return _objectWrapper;
        }

        public void SetObjectWrapper(IObjectWrapper objectWrapper)
        {
            _objectWrapper = objectWrapper;
        }

        /**
         * Wraps the passed object into a template model using this object's object
         * wrapper.
         * @param obj the object to wrap
         * @return the template model that wraps the object
         * @throws TemplateModelException if the wrapper does not know how to
         * wrap the passed object.
         */

        protected ITemplateModel Wrap(object obj)
        {
            return _objectWrapper.Wrap(obj);
        }
    }
}